package org.apache.james.hibernate.entity;

import javax.mail.Flags;
import javax.mail.Flags.Flag;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Transient;

@Entity
public class MailFlag {
	
	//MailFlagPk id = new MailFlagPk();
	int id;
	
	ImapUserInfo user;
	DbMailbox mailbox;
	Mail mail;

	// this is initialized from the mail object, just for easy querying
	long uid;
	
	boolean answered;
	boolean deleted;
	boolean draft;
	boolean flagged;
	boolean recent;
	boolean seen;

/*
	@Id
	public MailFlagPk getId() {
		return id;
	}
	
	public void setId(MailFlagPk id) {
		this.id = id;
	}
	
*/
	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}
	
	@ManyToOne(optional = false, fetch = FetchType.LAZY)
	public ImapUserInfo getUser() {
		return user;
	}

	public void setUser(ImapUserInfo user) {
		this.user = user;
	}

	@ManyToOne(optional = false, fetch = FetchType.LAZY)
	public DbMailbox getMailbox() {
		return mailbox;
	}

	public void setMailbox(DbMailbox mailbox) {
		this.mailbox = mailbox;
	}

	@ManyToOne(optional = false, cascade= {CascadeType.PERSIST, CascadeType.MERGE })
	public Mail getMail() {
		return mail;
	}

	public void setMail(Mail mail) {
		this.mail = mail;
	}

	
	public boolean isAnswered() {
		return answered;
	}
	public void setAnswered(boolean answered) {
		this.answered = answered;
	}
	public boolean isDeleted() {
		return deleted;
	}
	public void setDeleted(boolean deleted) {
		this.deleted = deleted;
	}
	public boolean isDraft() {
		return draft;
	}
	public void setDraft(boolean draft) {
		this.draft = draft;
	}
	public boolean isFlagged() {
		return flagged;
	}
	public void setFlagged(boolean flagged) {
		this.flagged = flagged;
	}
	public boolean isRecent() {
		return recent;
	}
	public void setRecent(boolean recent) {
		this.recent = recent;
	}
	public boolean isSeen() {
		return seen;
	}
	public void setSeen(boolean seen) {
		this.seen = seen;
	}
	
	public long getUid() {
		return uid;
	}
	
	public void setUid(long uid) {
		this.uid = uid;
	}
	
	
    @Transient
    public void setFlags(Flags flags) {
        setAnswered(flags.contains(Flags.Flag.ANSWERED));
        setDeleted(flags.contains(Flags.Flag.DELETED));
        setDraft(flags.contains(Flags.Flag.DRAFT));
        setFlagged(flags.contains(Flags.Flag.FLAGGED));
        setRecent(flags.contains(Flags.Flag.RECENT));
        setSeen(flags.contains(Flags.Flag.SEEN));
    }
    
    @Transient
    public Flags getFlagsObject() {
        Flags flags=new Flags();

        if (isAnswered()) {
            flags.add(Flags.Flag.ANSWERED);
        }
        if (isDeleted()) {
            flags.add(Flags.Flag.DELETED);
        }
        if (isDraft()) {
            flags.add(Flags.Flag.DRAFT);
        }
        if (isFlagged()) {
            flags.add(Flags.Flag.FLAGGED);
        }
        if (isRecent()) {
            flags.add(Flags.Flag.RECENT);
        }
        if (isSeen()) {
            flags.add(Flags.Flag.SEEN);
        }
        return flags;
    }

    @Override
    public String toString() {
    	
    	return "MailFlag[id:"+getId()+",uid:"+getUid()+",user:"+getUser().getId()+",mail:"+getMail().getId()+']';
    }
	
    public static String format(Flags flags, boolean replace, boolean addFlag) {
    	StringBuilder buf = new StringBuilder();
    	if (replace) {
    		format(buf, flags, Flags.Flag.ANSWERED, "answered", "true", "false");
    		format(buf, flags, Flags.Flag.DELETED, "deleted", "true", "false");
    		format(buf, flags, Flags.Flag.DRAFT, "draft", "true", "false");
    		format(buf, flags, Flags.Flag.FLAGGED, "flagged", "true", "false");
    		format(buf, flags, Flags.Flag.RECENT, "recent", "true", "false");
    		format(buf, flags, Flags.Flag.SEEN, "seen", "true", "false");
    	} else {
    		if (addFlag) {
        		format(buf, flags, Flags.Flag.ANSWERED, "answered", "true", null);
        		format(buf, flags, Flags.Flag.DELETED, "deleted", "true", null);
        		format(buf, flags, Flags.Flag.DRAFT, "draft", "true", null);
        		format(buf, flags, Flags.Flag.FLAGGED, "flagged", "true", null);
        		format(buf, flags, Flags.Flag.RECENT, "recent", "true", null);
        		format(buf, flags, Flags.Flag.SEEN, "seen", "true", null);
    		} else {
        		format(buf, flags, Flags.Flag.ANSWERED, "answered", "false", null);
        		format(buf, flags, Flags.Flag.DELETED, "deleted", "false", null);
        		format(buf, flags, Flags.Flag.DRAFT, "draft", "false", null);
        		format(buf, flags, Flags.Flag.FLAGGED, "flagged", "false", null);
        		format(buf, flags, Flags.Flag.RECENT, "recent", "false", null);
        		format(buf, flags, Flags.Flag.SEEN, "seen", "false", null);
    		}
    	}
    	return buf.toString();
    }

	private static void format(StringBuilder buf, Flags flags, Flag flag,
			String key, String containsValue, String notContainsValue) {
		if (flags.contains(flag)) {
			if (containsValue!=null) {
				if (buf.length()>0) { 
					buf.append(", ");
				}
				buf.append(key).append(" = ").append(containsValue);
			}
		} else {
			if (notContainsValue!=null) {
				if (buf.length()>0) { 
					buf.append(", ");
				}
				buf.append(key).append(" = ").append(notContainsValue);
			}
		}
	}
}
